//
// Created by 郝羽 on 2018/5/18.
//

#include <sys/socket.h>
#include <netinet/in.h>
#include <cstdio>
#include <arpa/inet.h>
#include <sys/time.h>
#include <cstdlib>
#include <string.h>

void print_usage(const char* prog) {
    fprintf(stdout, "%s <ip> <port start> <port stop>\n", prog);
}

int ping_udp_port(int sock, const char* ip, int port) {
    sockaddr_in sa;
    sa.sin_family = AF_INET;
    inet_aton(ip, &sa.sin_addr);
    sa.sin_port = htons(port);

    int s = sendto(sock, "hello\n", 6, 0, (sockaddr*)&sa, sizeof(sa));
    if (s < 0) {
        //fprintf(stderr, "ERROR: could not send ping: %d %s\n", s, strerror(s));
        return s;
    }

    char buf[65535];
    socklen_t sal = sizeof(sockaddr_in);
    auto r = recvfrom(sock, buf, sizeof(buf), 0, (sockaddr*)&sa, &sal);
    if (r < 0) {
        //fprintf(stderr, "ERROR: could not recv ping: %d %s\n", r, strerror(r));
        return r;
    }

    return 0;
}

int main(int argc, const char* argv[]) {

    auto sock = socket(AF_INET, SOCK_DGRAM, 0);
    if (sock < 0) {
        fprintf(stderr, "ERROR: could not create socket\n");
        return -1;
    }

    fprintf(stderr, "created socket  %d\n", sock);

    sockaddr_in sa;
    sa.sin_family = AF_INET;
    sa.sin_addr.s_addr = INADDR_ANY;
    sa.sin_port = 0;

    int ret = bind(sock, (sockaddr*)&sa, sizeof(sa));
    if (ret < 0) {
        fprintf(stderr, "ERROR: could not bind socket\n");
        return -1;
    }

    timeval tv;
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    ret = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
    if (ret < 0) {
        fprintf(stderr, "ERROR: could not set recv timeout\n");
    }


    if (argc != 4) {
        print_usage(argv[0]);
        return -1;
    }

    const char* ip = argv[1];
    int p_start = atoi(argv[2]);
    int p_stop = atoi(argv[3]);

    if (p_stop < p_start || p_stop == 0 || p_start == 0) {
        print_usage(argv[0]);
        return -1;
    }

    for (int i = p_start; i <= p_stop; i++) {
        int r = ping_udp_port(sock, ip, i);
        if (r < 0) {
            fprintf(stderr, "port %d error: %s\n", i, strerror(r));
        } else {
            fprintf(stderr, "port %d ok\n", i);
        }
    }

}